问题
有三条与优化有关的格言是每个人都应该知道的:
1. 很多计算上的过失都被归咎于效率(没有必要达到的效率),而不是任何其他的原因,——甚至包括盲目地做傻事。 ——William A.Wulf[Wulf72] 2. 不要去计校效率上的一些小小的得失,在97%的情况下。不成熟的优化才是一切问题的根源。 ——Donald E.Knuth[Knuth74] 3. 在优化方面,我们应该遵守两条规则: 规则1:不要进行优化。 规则2(仅针对专家):还是不要进行优化一一也就是说,在你还没有绝对清晰的未优化方案之前,请不要进行优化. ——M.A.Jackson[Jackson75]
在大多数情况下,不成熟的优化都会造成更严重的问题,在进行性能优化的时候应该着重关注于哪些方面?
答案
- 不要因为性能而牺牲合理的结构。要努力编写好的程序而不足快的栏序。如果好的程序不够快,它的结构将使它可以得到优化。好的程序体现了信息隐藏 (information hiding)的原则:只要有可能,它们就会把设计决策集中在单个模块中,因此,可以改变单个决策,而不会影响到系统的其他部分;
- 努力避免那些限制性能的设计决策。当一个系统设计完成之后,其中最难以更改的组件是那些指定了模块之间交互关系以及模块与外界交互关系的组件。在这些设计组件之中,最主要的是API协议以及永久数据格式。这些设计组件不仅在事后难以甚至不可能改变,而且它们都有可能对系统本该达到的性能产生严重的限制;
- 要考虑API设计决策的性能后果。使公有的类型成为可变的(mutable )。这可能会导致大量不必要的保护性拷贝(见第39条:必要时进行保护性拷贝 )。同样地,在适合使用复合模式的公有类中使用继承,会把这个类与它的超类永远地束缚在一起,从而人为地限制了子类的性能
结论
总而言之,不要费力去编写快速的程序——应该努力编写好的程序,速度自然会随之而来。在设计系统的时候,特别是在设计API、线路层协议和永久数据格式的时候,一定要考虑性能的因素。当构建完系统之后,要测量它的性能。如果它足够快,你的任务就完成了。如果不够快,则可以在性能剖析器的帮助下,找到问题的根源,然后设法优化系统中相关的部分。第一个步骤是检查所选择的算法:再多的底层优化也无法弥补算法的选择不当。必要时重复这个过程,在每次改变之后都要测量性能,直到满意为止。